/**
 * @param {string[]} foods
 * @param {string[]} cuisines
 * @param {number[]} ratings
 */
 var FoodRatings = function(foods, cuisines, ratings) {
    this.foodsMap = new Map();
    this.foodsMap2 = new Map();
    this.cuisinesMap = new Map();
    this.cuisinesMap1 = new Map();
    this.ratingsMap = new Map();
    this.ratingsMap1 = new Map();
    this.foodNameMap = new Map();
    let foodNames = [...foods].sort();
    // console.log('foods: ', foods);
    // console.log('foodNames: ', foodNames);
    this.foodNames = foodNames;
    for(let i = 0; i < foodNames.length; i++){
        this.foodNameMap.set(foodNames[i],i);
    }
    // console.log('foodNameMap: ', this.foodNameMap);
    for(let i = 0; i < foods.length; i++){
        this.foodsMap.set(foods[i],ratings[i]);
        this.foodsMap2.set(foods[i],cuisines[i]);
        let cuisinesList = this.cuisinesMap.get(cuisines[i]) || new MaxPriorityQueue();
        cuisinesList.enqueue(ratings[i]);
        this.cuisinesMap.set(cuisines[i],cuisinesList);
        let cuisinesList1 = this.cuisinesMap1.get(cuisines[i]) || new Set();
        cuisinesList1.add(foods[i]);
        this.cuisinesMap1.set(cuisines[i],cuisinesList1);
        let foodsList = this.ratingsMap.get(ratings[i]) || new MinPriorityQueue();
        let foodsList1 = this.ratingsMap1.get(ratings[i]) || new Set();
        foodsList1.add(foods[i]);
        foodsList.enqueue(this.foodNameMap.get(foods[i]));
        this.ratingsMap.set(ratings[i],foodsList);
        // console.log('ratingsMap: ', ratings[i],foodsList.toArray());
        this.ratingsMap1.set(ratings[i],foodsList1);
    }
    // console.log(this.foodsMap);
    // console.log(this.cuisinesMap);
    // console.log(this.ratingsMap);
    // console.log(this.foodNames);
};

/** 
 * @param {string} food 
 * @param {number} newRating
 * @return {void}
 */
FoodRatings.prototype.changeRating = function(food, newRating) {
    let rate = this.foodsMap.get(food);
    let cuisine = this.foodsMap2.get(food);
    this.foodsMap.set(food,newRating);
    let cuisinesList = this.cuisinesMap.get(cuisine) || new MaxPriorityQueue();
    cuisinesList.enqueue(newRating);
    this.cuisinesMap.set(cuisine,cuisinesList);
    let foodsList = this.ratingsMap.get(newRating) || new MinPriorityQueue();
    // if(newRating == 2) console.log('111',newRating,foodsList.toArray());
    foodsList.enqueue(this.foodNameMap.get(food));
    // if(newRating == 2) console.log('222',newRating,foodsList.toArray());
    this.ratingsMap.set(newRating,foodsList);
    let foodsList1 = this.ratingsMap1.get(rate);
    foodsList1.delete(food);
    this.ratingsMap1.set(rate,foodsList1);
    foodsList1 = this.ratingsMap1.get(newRating) || new Set();
    foodsList1.add(food);
    this.ratingsMap1.set(newRating,foodsList1);
};

/** 
 * @param {string} cuisine
 * @return {string}
 */
FoodRatings.prototype.highestRated = function(cuisine) {
    // console.log('---------');
    let foodSet = this.cuisinesMap1.get(cuisine);
    let scores = this.cuisinesMap.get(cuisine);
    // console.log('scores: ', scores.toArray());
    let score = scores.front().element;
    // console.log('score: ', score);
    let foods = this.ratingsMap.get(score);
    // console.log('foods: ', foods.toArray());
    let food = foods.front();
    while(!food){
        scores.dequeue();
            score = scores.front();
            if(score) score = score.element;
            foods = this.ratingsMap.get(score);
            if(foods) food = foods.front();
    }
    food = food.element;
    food = this.foodNames[food];
    // console.log('food: ', food);
    // console.log('this.ratingsMap1.get(score)',this.ratingsMap1.get(score));
    // console.log('foodSet',foodSet);
    if(foodSet.size == 1) return [...foodSet][0];
    while(!foodSet.has(food) || !this.ratingsMap1.get(score) || !this.ratingsMap1.get(score).has(food)){
        foods.dequeue();
        food = foods.front();
         while(!food){
            scores.dequeue();
            score = scores.front();
            if(score) score = score.element;
            foods = this.ratingsMap.get(score);
            if(foods) {food = foods.front();
                // console.log('foods: ', foods.toArray());
            }
         }
            food = food.element;
            food = this.foodNames[food];
            // console.log('food',food);
    }
    return food;
};

/**
 * Your FoodRatings object will be instantiated and called as such:
 * var obj = new FoodRatings(foods, cuisines, ratings)
 * obj.changeRating(food,newRating)
 * var param_2 = obj.highestRated(cuisine)
 */